package com.example.myapplication.ui.gallery;

import android.os.StrictMode;
import android.util.JsonReader;
import android.util.Log;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import com.example.myapplication.ScanEntry;
import com.example.myapplication.Scanner;

import java.io.IOException;
import java.io.StringReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import pojo.PLD_daemon;
import pojo.Timed;

public class GalleryViewModel extends ViewModel {

    private String mainIp;

    private final MutableLiveData<String> mText;
    private final MutableLiveData<List<ScanEntry>> objects;
    private Scanner scanner;

    public GalleryViewModel() {
        mText = new MutableLiveData<>();
        objects = new MutableLiveData<>();
        objects.postValue(Collections.emptyList());
    }

    public LiveData<String> getText() {
        return mText;
    }

    public MutableLiveData<List<ScanEntry>> getObjects() {
        return objects;
    }

    public void discoverNetworkOf(String mainIp) {
        if (this.mainIp == null) {
            this.mainIp = mainIp;
            try {
                Inet4Address inet4Address = (Inet4Address) Inet4Address.getByName(mainIp);
                HashMap<String, Timed> list = new HashMap<>();

                PLD_daemon daemon = new PLD_daemon();
                daemon.setTitle("home");
                this.objects.postValue(Arrays.asList(new ScanEntry(inet4Address, daemon, list)));
                scanner = new Scanner(inet4Address);
                scanner.setLogger(mText::postValue);
                scanner.scan();
                mText.postValue("" + scanner.getFoundEntries().size());

                if (!scanner.getFoundEntries().isEmpty()) {
                    objects.postValue(new ArrayList<>(scanner.getFoundEntries().values()));
                }
            } catch (Throwable e) {
                mText.postValue("m " + e.getMessage());
                e.printStackTrace();
            }
        }
    }

    public String sendBroadcast() {

        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

        String message = "";



        try {
            DatagramSocket socket = new DatagramSocket();
            socket.setBroadcast(true);
            byte[] sendData = "{\"type\": \"discovery\"}".getBytes();
            InetAddress broadcastAddress = InetAddress.getByName("255.255.255.255");
            Log.i("UDP",getClass().getName() + "Main address: " + broadcastAddress.getHostAddress());
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, broadcastAddress, 2021);
            socket.send(sendPacket);
            Log.i("UDP",getClass().getName() + "Broadcast packet sent to: " + broadcastAddress.getHostAddress());
            socket.close();
        } catch (IOException e) {
            Log.e("UDP", "IOException: " + e.getMessage(), e);
            message += "1 " + e.getMessage() + " ";
        }

        try {
            DatagramSocket socket = new DatagramSocket(2021, InetAddress.getLocalHost());
            socket.setBroadcast(true);

            Log.i("UDP","Ready to receive broadcast packets! " + InetAddress.getLocalHost());

            byte[] recvBuf = new byte[15000];
            DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
            socket.receive(packet);

            Log.i("UDP", "Packet received from: " + packet.getAddress().getHostAddress());
            String data = new String(packet.getData()).trim();
            Log.i("UDP", "Packet received; data: " + data);

            socket.close();
            return data;
        }  catch (IOException ex) {
            Log.i("UDP", "Oops" + ex.getMessage(), ex);
            message += "2 " + ex.getMessage();
        }
        return message;
    }

    public void postLog(String selected) {
        mText.postValue(selected);
    }
}